#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.basic.security.filter;

import ${package}.basic.security.imagecode.ImageCode;
import ${package}.common.component.service.RedisService;
import ${package}.common.exception.ValidateCodeException;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Description: 验证码拦截器
 *
 * @author wupanhua
 * @date 2020-02-14 17:53
 *
 * <pre>
 *              ${copyright}
 *      Copyright (c) 2019. All Rights Reserved.
 * </pre>
 */
@AllArgsConstructor
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter {

	/**
	 * spring security 异常异常处理器
	 */
	private AuthenticationFailureHandler authenticationFailureHandler;
	/**
	 * 存储
	 */
	private RedisService redisService;

	/**
	 * Description:
	 *
	 * @author wupanhua
	 * @date 13:55 2020-05-15
	 **/
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

		try {
			//状态为0的时候不需要请求验证码，状态为1的时候需要请求验证码
			String status = "0";
			String userName = request.getParameter("username");
			Object number = redisService.get(userName);
			//number为0时不需要通过验证码校验
			if (null != number && !status.equals(number)) {
				validate(request);
			}

		} catch (ValidateCodeException e) {
			authenticationFailureHandler.onAuthenticationFailure(request, response, e);
			return;
		}
		filterChain.doFilter(request, response);
	}

	private void validate(HttpServletRequest request) throws ServletRequestBindingException {

		// 获取存放在session中的验证码
		Object imageCode = null;
		String token;
		try {
			token = ServletRequestUtils.getStringParameter(request, "token");
			if (null != token) {
				imageCode = redisService.get(token);
			}
		} catch (ServletRequestBindingException e) {
			log.error("获取验证码异常");
		}
		if (imageCode == null) {
			throw new ValidateCodeException("验证码不存在");
		}
		ImageCode codeInSession = JSON.parseObject(String.valueOf(imageCode), ImageCode.class);

		String codeInRequest = ServletRequestUtils.getStringParameter(request, "code");

		if (StringUtils.isBlank(codeInRequest)) {
			throw new ValidateCodeException("验证码值不能为空");
		}

		if (codeInSession.isExpried()) {
			throw new ValidateCodeException("验证码已过期");
		}

		if (!StringUtils.equals(codeInSession.getCode(), codeInRequest)) {
			throw new ValidateCodeException("验证码不匹配");
		}
		//设置过期时间为12小时
		redisService.remove(request.getParameter("username"));
		redisService.remove(request.getParameter("token"));
	}
}


